// MIT License
//
// Copyright(c) 2021 Jaf932074323
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this softwareand associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright noticeand this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// 2025-5-6 姜安富
#include "gtest/gtest.h"
#include "const_string.h"
#include <string>
#include <algorithm>
#include <array>
#include <stdint.h>

template<size_t Capacity1, size_t Capacity2>
static void TestEquality(const jaf::ConstString< Capacity1>& str1, const char(&str2)[Capacity2])
{
	bool a = str1 == str2;
	EXPECT_EQ(str1.data[str1.Size()], (char)0);
	EXPECT_EQ(str1, str2);
	EXPECT_EQ(str1.Size(), sizeof(str2) - 1);
}

TEST(constr, usually)
{
	constexpr jaf::ConstString demo_1 = jaf::ConstString("123");
	constexpr jaf::ConstString demo_2 = jaf::ConstString({ '4', '5', '6', '\0' });
	constexpr jaf::ConstString demo_3 = demo_1 + demo_2;
	constexpr jaf::ConstString demo_4 = demo_1 + 'a';
	constexpr jaf::ConstString demo_5 = 'a' + demo_1;
	constexpr jaf::ConstString demo_6 = demo_1 + "abc";
	constexpr jaf::ConstString demo_7 = "abc" + demo_1;
	constexpr jaf::ConstString demo_8 = jaf::ConstString('a');
	constexpr jaf::ConstString demo_9 = jaf::ConstString();

	TestEquality(demo_1, "123");
	TestEquality(demo_2, "456");
	TestEquality(demo_3, "123456");
	TestEquality(demo_4, "123a");
	TestEquality(demo_5, "a123");
	TestEquality(demo_6, "123abc");
	TestEquality(demo_7, "abc123");
	TestEquality(demo_8, "a");
	TestEquality(demo_9, "");
}

TEST(constr, substr)
{
    constexpr jaf::ConstString con_str = jaf::ConstString("abc123");

	constexpr jaf::ConstString remove_prefix_0 = con_str.RemovePrefix<0>();
	constexpr jaf::ConstString remove_prefix_3 = con_str.RemovePrefix<3>();
	constexpr jaf::ConstString remove_prefix_6 = con_str.RemovePrefix<6>();
	constexpr jaf::ConstString remove_prefix_7 = con_str.RemovePrefix<7>();
	constexpr jaf::ConstString remove_prefix_10 = con_str.RemovePrefix<10>();
	TestEquality(remove_prefix_0, "abc123");
	TestEquality(remove_prefix_3, "123");
	TestEquality(remove_prefix_6, "");
	TestEquality(remove_prefix_7, "");
	TestEquality(remove_prefix_10, "");

	constexpr jaf::ConstString remove_suffix_0 = con_str.RemoveSuffix<0>();
	constexpr jaf::ConstString remove_suffix_3 = con_str.RemoveSuffix<3>();
	constexpr jaf::ConstString remove_suffix_6 = con_str.RemoveSuffix<6>();
	constexpr jaf::ConstString remove_suffix_7 = con_str.RemoveSuffix<7>();
	constexpr jaf::ConstString remove_suffix_10 = con_str.RemoveSuffix<10>();
	TestEquality(remove_suffix_0, "abc123");
	TestEquality(remove_suffix_3, "abc");
	TestEquality(remove_suffix_6, "");
	TestEquality(remove_suffix_7, "");
	TestEquality(remove_suffix_10, "");

	constexpr jaf::ConstString remove_substr_0_0 = con_str.SubStr<0, 0>();
	constexpr jaf::ConstString remove_substr_0_3 = con_str.SubStr<0, 3>();
	constexpr jaf::ConstString remove_substr_0_7 = con_str.SubStr<0, 7>();
	constexpr jaf::ConstString remove_substr_0 = con_str.SubStr<0>();
	constexpr jaf::ConstString remove_substr_3_0 = con_str.SubStr<3, 0>();
	constexpr jaf::ConstString remove_substr_3_2 = con_str.SubStr<3, 2>();
	constexpr jaf::ConstString remove_substr_3_3 = con_str.SubStr<3, 3>();
	constexpr jaf::ConstString remove_substr_3_4 = con_str.SubStr<3, 4>();
	constexpr jaf::ConstString remove_substr_3 = con_str.SubStr<3>();
	TestEquality(remove_substr_0_0, "");
	TestEquality(remove_substr_0_3, "abc");
	TestEquality(remove_substr_0_7, "abc123");
	TestEquality(remove_substr_0, "abc123");
	TestEquality(remove_substr_3_0, "");
	TestEquality(remove_substr_3_2, "12");
	TestEquality(remove_substr_3_3, "123");
	TestEquality(remove_substr_3_4, "123");
	TestEquality(remove_substr_3, "123");
}

namespace
{
	template<jaf::ConstString PropertyName>
	class Property
	{
	};

	class Student
	{
	public:
		uint32_t& GetProperty(Property<"age">)
		{
			return age_;
		}

		double& GetProperty(Property<"weight">)
		{
			return weight_;
		}

	public:
		uint32_t age_ = 0;
		double weight_ = 0;
	};
}

TEST(constr, template_parameter)
{
	Student student;
	student.GetProperty(Property<"age">()) = 30;
	student.GetProperty(Property<"weight">()) = 120;

	EXPECT_EQ(&student.GetProperty(Property<"age">()), &student.age_);
	EXPECT_EQ(&student.GetProperty(Property<"weight">()), &student.weight_);
}
